from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import HTTPException
from pydantic import BaseModel, Field

from module_admin.entity.vo.common_vo import CrudResponseModel
from module_kylin.dao.future_strategy_param_dao import FutureStrategyParamDao
from module_kylin.entity.vo.future_strategy_param_vo import (
    FutureStrategyParamModel,
    FutureStrategyParamPageQueryModel,
    DeleteFutureStrategyParamModel,
)


class FutureStrategyParamService:
    """
    期货策略参数服务层
    """

    @classmethod
    async def get_strategy_param_list(cls, db: AsyncSession, query_model: FutureStrategyParamPageQueryModel, 
                                     is_page: bool = False):
        """
        获取策略参数列表

        :param db: 数据库会话
        :param query_model: 查询参数
        :param is_page: 是否开启分页
        :return: 策略参数列表
        """
        try:
            # 获取策略参数列表
            strategy_param_page = await FutureStrategyParamDao.get_strategy_param_list(db, query_model, is_page)

            return strategy_param_page
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def get_strategy_param_detail(cls, db: AsyncSession, param_id: int):
        """
        获取策略参数详情

        :param db: 数据库会话
        :param param_id: 参数id
        :return: 策略参数详情
        """
        try:
            # 获取策略参数详情
            strategy_param_detail = await FutureStrategyParamDao.get_strategy_param_by_id(db, param_id)

            if not strategy_param_detail:
                raise HTTPException(status_code=404, detail=f"策略参数{param_id}不存在")

            return strategy_param_detail
        except HTTPException as e:
            raise e
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def add_strategy_param(cls, db: AsyncSession, param: FutureStrategyParamModel):
        """
        添加策略参数

        :param db: 数据库会话
        :param param: 策略参数信息
        :return: 操作结果
        """
        try:
            # 检查必填字段
            if not param.strategy_instance or not param.param_name:
                raise HTTPException(status_code=400, detail="策略实例名称和参数名称不能为空")

            # 检查策略参数是否已存在
            existing_param = await FutureStrategyParamDao.get_strategy_param_by_info(db, param)
            if existing_param:
                raise HTTPException(status_code=400, detail=f"{param.strategy_instance}的{param.param_name}参数已存在")

            # 添加策略参数
            new_param = await FutureStrategyParamDao.add_strategy_param(db, param)
            await db.commit()

            return new_param
        except HTTPException as e:
            await db.rollback()
            raise e
        except Exception as e:
            await db.rollback()
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def update_strategy_param(cls, db: AsyncSession, param_id: int, param: FutureStrategyParamModel):
        """
        更新策略参数

        :param db: 数据库会话
        :param param_id: 参数id
        :param param: 策略参数信息
        :return: 操作结果
        """
        try:
            # 检查策略参数是否存在
            existing_param = await FutureStrategyParamDao.get_strategy_param_by_id(db, param_id)
            if not existing_param:
                raise HTTPException(status_code=404, detail=f"策略参数{param_id}不存在")

            # 如果更新了策略实例名称和参数名，检查是否与其他记录冲突
            if param.strategy_instance and param.param_name and (
                    param.strategy_instance != existing_param.strategy_instance or param.param_name != existing_param.param_name):
                check_param = FutureStrategyParamModel(
                    strategy_instance=param.strategy_instance,
                    param_name=param.param_name
                )
                conflict_param = await FutureStrategyParamDao.get_strategy_param_by_info(db, check_param)
                if conflict_param and conflict_param.id != param_id:
                    raise HTTPException(status_code=400, detail=f"{param.strategy_instance}的{param.param_name}参数已存在")

            # 更新策略参数
            await FutureStrategyParamDao.update_strategy_param(db, param_id, param)
            await db.commit()

            return existing_param
        except HTTPException as e:
            await db.rollback()
            raise e
        except Exception as e:
            await db.rollback()
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def delete_strategy_param(cls, db: AsyncSession, delete_model: DeleteFutureStrategyParamModel):
        """
        删除策略参数

        :param db: 数据库会话
        :param delete_model: 删除参数
        :return: 操作结果
        """
        try:
            # 检查策略参数是否存在
            for param_id in delete_model.ids:
                existing_param = await FutureStrategyParamDao.get_strategy_param_by_id(db, param_id)
                if not existing_param:
                    raise HTTPException(status_code=404, detail=f"策略参数{param_id}不存在")

            # 批量删除策略参数
            await FutureStrategyParamDao.batch_delete_strategy_param(db, delete_model.ids)
            await db.commit()

            return CrudResponseModel(is_success=True, message='删除成功')
        except HTTPException as e:
            await db.rollback()
            raise e
        except Exception as e:
            await db.rollback()
            raise HTTPException(status_code=500, detail=str(e))

    @classmethod
    async def truncate_strategy_param(cls, db: AsyncSession):
        """
        清空全部策略参数

        :param db: 数据库会话
        :return: 操作结果
        """
        try:
            # 清空全部策略参数
            await FutureStrategyParamDao.truncate_strategy_param(db)
            await db.commit()

            return CrudResponseModel(is_success=True, message='清空成功')
        except Exception as e:
            await db.rollback()
            raise HTTPException(status_code=500, detail=str(e))